#include <boost/bind.hpp>
#include "MceIrSession.h"
#include "Publisher.h"
#include "Parsers.h"
#include "RegKey.h"
#include "MceTimings.h"
#include <sstream>


MceIrSession::MceIrSession(boost::asio::io_service& io_service, DriverManager * driverManager) : TcpSession(io_service), m_irReceiveId(-1), m_DriverManager(driverManager)
{

}

void MceIrSession::start()
{
	TcpSession::start();
	m_irReceiveId = m_DriverManager->publisher()->add(boost::bind( &MceIrSession::irReceived, this,_1,_2,_3,_4 ));
}


MceIrSession::~MceIrSession()
{
	if ( m_irReceiveId >= 0 )
		m_DriverManager->publisher()->remove(m_irReceiveId);		
}

void MceIrSession::irReceived ( DWORD protocol, DWORD key, DWORD repeat, const char * name )
{
	char buf[1000];
	sprintf_s(buf,1000, "R %d %d %d %s\r\n", protocol, key, repeat, name);
	send(buf);
}

void MceIrSession::transmit ( const std::string & data )
{
	UIntVector iv;
	unsigned int hardwareId = 0;
	unsigned int blasters = 0;
	unsigned int repeats = 0;

	if ( transmitParser( data, iv, hardwareId, blasters, repeats ) )
	{
		MceTimings t;

		t.setBlasters(blasters);
		if ( ! t.fromCCF(iv, repeats) )
		{
			send("t error CCF parse failure.\r\n");
			return;
		}
		
		if ( hardwareId >= m_DriverManager->get().size() )
		{
			send("t error invalid index\r\n");
			return;
		}
		
		IMceIrDrvPtr driver = m_DriverManager->get()[hardwareId];
		

		if ( driver->transmit( t.getTimings(), t.getCount(), t.getBlasters(), (PtrSize) (1000000 / t.getFrequency())) )
		{
			send("t OK\r\n");
		}
		else
		{
			send("t error blasting.\r\n");
		}
		
	}
	else
	{
		send("t error Parse failed.\r\n");
	}
}

void MceIrSession::status ()
{
	if ( m_DriverManager->get().size() == 0 )
	{
		send("s HARDWARE_NOT_CONNECTED\r\n");
		return;
	}

	DriverManager::DriverList::iterator begin = m_DriverManager->get().begin();
	DriverManager::DriverList::iterator end = m_DriverManager->get().end();

	std::stringstream s;
	s << "s " <<  m_DriverManager->get().size() << " ";
	while ( begin != end )
	{
		IMceIrDrvPtr driver = *begin;
		s << driver->getPath() << " ";
		begin++;
	}

	s << "\r\n";
	send(s.str());
}


void MceIrSession::blasters ()
{
	if ( m_DriverManager->get().size() == 0 )
	{
		send("b error no hardware found.\r\n");
		return;
	}

	DriverManager::DriverList::iterator begin = m_DriverManager->get().begin();
	DriverManager::DriverList::iterator end = m_DriverManager->get().end();
	
	std::stringstream s;

	s << "b ";
	while ( begin != end )
	{
		IMceIrDrvPtr driver = *begin;
		PtrSize tx;
		if ( driver->getTransmitMask(tx) )
			s << tx << " ";
		else
			s << "0 ";
		begin++;
	}
	s << "\r\n";
	send(s.str());
}

bool MceIrSession::dataReceived ( const char * data, size_t len )
{
	if ( len == 0 )
		return true;
	
	std::string s(data, len);

	switch (data[0] )
	{
	case 'q' :
		send("q OK\r\n");
		return false;
	case 'i' :
		{
			std::stringstream s;
			s << "i " << NAMEANDVERSION << "\r\n";
			send ( s.str() );
			break;
		}
	case 't' :
		transmit ( s );
		break;
	case 's' :
		status ( );
		break;
	case 'b' :
		blasters ();
		break;
	default:
		send("e Unknown command\r\n");
	}

	return true;
}